home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / drivers / char / vt.c < prev   
Encoding:
C/C++ Source or Header  |  1994-06-05  |  14.5 KB  |  626 lines

  1. /*
  2.  *  kernel/chr_drv/vt.c
  3.  *
  4.  *  Copyright (C) 1992 obz under the linux copyright
  5.  *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
  6.  */
  7.  
  8. #undef __pc_stuf__
  9.  
  10. #include <linux/types.h>
  11. #include <linux/config.h>
  12. #include <linux/errno.h>
  13. #include <linux/sched.h>
  14. #include <linux/tty.h>
  15. #include <linux/timer.h>
  16. #include <linux/kernel.h>
  17. #include <linux/kd.h>
  18. #include <linux/vt.h>
  19. #include <linux/string.h>
  20.  
  21. #ifdef __pc_stuff__
  22. #include <asm/io.h>
  23. #endif
  24. #include <asm/segment.h>
  25.  
  26. #include "kbd_kern.h"
  27. #include "vt_kern.h"
  28. #include "diacr.h"
  29.  
  30. /*
  31.  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
  32.  * experimentation and study of X386 SYSV handling.
  33.  *
  34.  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
  35.  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
  36.  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
  37.  * always treat our set of vt as numbered 1..NR_CONSOLES (corresponding to
  38.  * ttys 0..NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
  39.  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
  40.  * to the current console is done by the main ioctl code.
  41.  */
  42.  
  43. struct vt_struct vt_cons[NR_CONSOLES];
  44.  
  45. asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
  46.  
  47. extern void compute_shiftstate(void);
  48. extern void change_console(unsigned int new_console);
  49. extern void complete_change_console(unsigned int new_console);
  50. extern int vt_waitactive(void);
  51.  
  52. /*
  53.  * routines to load custom translation table and EGA/VGA font from console.c
  54.  */
  55. extern int con_set_trans(char * table);
  56. extern int con_get_trans(char * table);
  57. extern int con_set_font(char * fontmap);
  58. extern int con_get_font(char * fontmap);
  59.  
  60. /*
  61.  * these are the valid i/o ports we're allowed to change. they map all the
  62.  * video ports
  63.  */
  64. #define GPFIRST 0x3b4
  65. #define GPLAST 0x3df
  66. #define GPNUM (GPLAST - GPFIRST + 1)
  67.  
  68. #ifdef __pc_stuff__
  69.  
  70. /*
  71.  * Generates sound of some count for some number of clock ticks
  72.  * [count = 1193180 / frequency]
  73.  *
  74.  * If freq is 0, will turn off sound, else will turn it on for that time.
  75.  * If msec is 0, will return immediately, else will sleep for msec time, then
  76.  * turn sound off.
  77.  *
  78.  * We use the BEEP_TIMER vector since we're using the same method to
  79.  * generate sound, and we'll overwrite any beep in progress. That may
  80.  * be something to fix later, if we like.
  81.  *
  82.  * We also return immediately, which is what was implied within the X
  83.  * comments - KDMKTONE doesn't put the process to sleep.
  84.  */
  85. static void
  86. kd_nosound(unsigned long ignored)
  87. {
  88.     /* disable counter 2 */
  89.     outb(inb_p(0x61)&0xFC, 0x61);
  90.     return;
  91. }
  92.  
  93. void
  94. kd_mksound(unsigned int count, unsigned int ticks)
  95. {
  96.     static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
  97.  
  98.     cli();
  99.     del_timer(&sound_timer);
  100.     if (count) {
  101.         /* enable counter 2 */
  102.         outb_p(inb_p(0x61)|3, 0x61);
  103.         /* set command for counter 2, 2 byte write */
  104.         outb_p(0xB6, 0x43);
  105.         /* select desired HZ */
  106.         outb_p(count & 0xff, 0x42);
  107.         outb((count >> 8) & 0xff, 0x42);
  108.  
  109.         if (ticks) {
  110.             sound_timer.expires = ticks;
  111.             add_timer(&sound_timer);
  112.         }
  113.     } else
  114.         kd_nosound(0);
  115.     sti();
  116.     return;
  117. }
  118. #else
  119.  
  120. static void
  121. kd_nosound(unsigned long ignored)
  122. {
  123.     if (mach_mksound)
  124.         mach_mksound( 0, 0 );
  125. }
  126.  
  127. void
  128. kd_mksound(unsigned int count, unsigned int ticks)
  129. {
  130.     if (mach_mksound)
  131.         mach_mksound( count, ticks );
  132. }
  133.  
  134. #endif
  135.  
  136. /*
  137.  * We handle the console-specific ioctl's here.  We allow the
  138.  * capability to modify any console, not just the fg_console. 
  139.  */
  140. int vt_ioctl(struct tty_struct *tty, struct file * file,
  141.          unsigned int cmd, unsigned long arg)
  142. {
  143.     int console, i;
  144.     unsigned char ucval;
  145.     struct kbd_struct * kbd;
  146.  
  147.     console = tty->line - 1;
  148.  
  149.     if (console < 0 || console >= NR_CONSOLES)
  150.         return -EINVAL;
  151.  
  152.     kbd = kbd_table + console;
  153.     switch (cmd) {
  154.     case KIOCSOUND:
  155.         kd_mksound((unsigned int)arg, 0);
  156.         return 0;
  157.  
  158.     case KDMKTONE:
  159.     {
  160.         unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
  161.  
  162.         /*
  163.          * Generate the tone for the appropriate number of ticks.
  164.          * If the time is zero, turn off sound ourselves.
  165.          */
  166.         kd_mksound(arg & 0xffff, ticks);
  167.         if (ticks == 0)
  168.             kd_nosound(0);
  169.         return 0;
  170.     }
  171.  
  172.     case KDGKBTYPE:
  173.         /*
  174.          * this is naive.
  175.          */
  176.         i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
  177.         if (!i)
  178.             put_fs_byte(KB_101, (char *) arg);
  179.         return i;
  180.  
  181. #ifdef __pc_stuff__
  182.     case KDADDIO:
  183.     case KDDELIO:
  184.         /*
  185.          * KDADDIO and KDDELIO may be able to add ports beyond what
  186.          * we reject here, but to be safe...
  187.          */
  188.         if (arg < GPFIRST || arg > GPLAST)
  189.             return -EINVAL;
  190.         return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
  191.  
  192.     case KDENABIO:
  193.     case KDDISABIO:
  194.         return sys_ioperm(GPFIRST, GPNUM,
  195.                   (cmd == KDENABIO)) ? -ENXIO : 0;
  196. #endif
  197.  
  198.     case KDSETMODE:
  199.         /*
  200.          * currently, setting the mode from KD_TEXT to KD_GRAPHICS
  201.          * doesn't do a whole lot. i'm not sure if it should do any
  202.          * restoration of modes or what...
  203.          */
  204.         switch (arg) {
  205.         case KD_GRAPHICS:
  206.             break;
  207.         case KD_TEXT0:
  208.         case KD_TEXT1:
  209.             arg = KD_TEXT;
  210.         case KD_TEXT:
  211.             break;
  212.         default:
  213.             return -EINVAL;
  214.         }
  215.         if (vt_cons[console].vc_mode == (unsigned char) arg)
  216.             return 0;
  217.         vt_cons[console].vc_mode = (unsigned char) arg;
  218.         if (console != fg_console)
  219.             return 0;
  220.         /*
  221.          * explicitly blank/unblank the screen if switching modes
  222.          */
  223. #ifdef __notyet__
  224.         if (arg == KD_TEXT)
  225.             unblank_screen();
  226.         else {
  227.             timer_active &= ~(1<<BLANK_TIMER);
  228.             blank_screen();
  229.         }
  230. #endif
  231.         return 0;
  232.  
  233.     case KDGETMODE:
  234.         i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
  235.         if (!i)
  236.             put_fs_long(vt_cons[console].vc_mode, (unsigned long *) arg);
  237.         return i;
  238.  
  239.     case KDMAPDISP:
  240.     case KDUNMAPDISP:
  241.         /*
  242.          * these work like a combination of mmap and KDENABIO.
  243.          * this could be easily finished.
  244.          */
  245.         return -EINVAL;
  246.  
  247.     case KDSKBMODE:
  248.         switch(arg) {
  249.           case K_RAW:
  250.                 set_vc_kbd_mode(kbd, VC_RAW);
  251.             clr_vc_kbd_mode(kbd, VC_MEDIUMRAW);
  252.             break;
  253.           case K_MEDIUMRAW:
  254.             clr_vc_kbd_mode(kbd, VC_RAW);
  255.             set_vc_kbd_mode(kbd, VC_MEDIUMRAW);
  256.             break;
  257.           case K_XLATE:
  258.             clr_vc_kbd_mode(kbd, VC_RAW);
  259.             clr_vc_kbd_mode(kbd, VC_MEDIUMRAW);
  260.             compute_shiftstate();
  261.             break;
  262.           default:
  263.             return -EINVAL;
  264.         }
  265.         flush_input(tty);
  266.         return 0;
  267.  
  268.     case KDGKBMODE:
  269.         i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
  270.         if (!i) {
  271.             ucval = (vc_kbd_mode(kbd, VC_RAW) ? K_RAW :
  272.                  vc_kbd_mode(kbd, VC_MEDIUMRAW) ? K_MEDIUMRAW :
  273.                  K_XLATE);
  274.             put_fs_long(ucval, (unsigned long *) arg);
  275.         }
  276.         return i;
  277.  
  278.     /* this could be folded into KDSKBMODE, but for compatibility
  279.        reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
  280.     case KDSKBMETA:
  281.         switch(arg) {
  282.           case K_METABIT:
  283.             clr_vc_kbd_mode(kbd, VC_META);
  284.             break;
  285.           case K_ESCPREFIX:
  286.             set_vc_kbd_mode(kbd, VC_META);
  287.             break;
  288.           default:
  289.             return -EINVAL;
  290.         }
  291.         return 0;
  292.  
  293.     case KDGKBMETA:
  294.         i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
  295.         if (!i) {
  296.             ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
  297.                  K_METABIT);
  298.             put_fs_long(ucval, (unsigned long *) arg);
  299.         }
  300.         return i;
  301.  
  302.     case KDGKBENT:
  303.     {
  304.         struct kbentry * const a = (struct kbentry *)arg;
  305.         u_char s;
  306.  
  307.         i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
  308.         if (i)
  309.             return i;
  310.         if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
  311.             return -EINVAL;
  312.         if ((s = get_fs_byte((char *) &a->kb_table)) >= NR_KEYMAPS)
  313.             return -EINVAL;
  314.         put_fs_word(key_map[s][i], (short *) &a->kb_value);
  315.         return 0;
  316.     }
  317.  
  318.     case KDSKBENT:
  319.     {
  320.         const struct kbentry * a = (struct kbentry *)arg;
  321.         u_char s;
  322.         u_short v;
  323.  
  324.         i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbentry));
  325.         if (i)
  326.             return i;
  327.         if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
  328.             return -EINVAL;
  329.         if ((s = get_fs_byte((char *) &a->kb_table)) >= NR_KEYMAPS)
  330.             return -EINVAL;
  331.         if (KTYP(v = get_fs_word(&a->kb_value)) >= NR_TYPES)
  332.             return -EINVAL;
  333.         if (KVAL(v) > max_vals[KTYP(v)])
  334.             return -EINVAL;
  335.         key_map[s][i] = v;
  336.         return 0;
  337.     }
  338.  
  339.     case KDGKBSENT:
  340.     {
  341.         struct kbsentry *a = (struct kbsentry *)arg;
  342.         char *p;
  343.         u_char *q;
  344.  
  345.         i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
  346.         if (i)
  347.             return i;
  348.         if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC || i < 0)
  349.             return -EINVAL;
  350.         q = a->kb_string;
  351.         p = func_table[i];
  352.         if(!p) {
  353.             /* beware of tables generated for a smaller NR_FUNC */
  354.             printk("KDGKBSENT error: func_table[%d] is nil.\n",
  355.                i);
  356.             return -EINVAL;
  357.         }
  358.         for ( ; *p; p++)
  359.             put_fs_byte(*p, q++);
  360.         put_fs_byte(0, q);
  361.         return 0;
  362.     }
  363.  
  364.     case KDSKBSENT:
  365.     {
  366.         struct kbsentry * const a = (struct kbsentry *)arg;
  367.         int delta;
  368.         char *first_free;
  369.         int k;
  370.         u_char *p;
  371.         char *q;
  372.  
  373.         i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
  374.         if (i)
  375.             return i;
  376.         if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC)
  377.             return -EINVAL;
  378.         q = func_table[i];
  379.         if (!q) {
  380.             /* beware of tables generated for a smaller NR_FUNC */
  381.             printk("KDSKBSENT error: func_table[%d] is nil.\n",
  382.                i);
  383.             return -EINVAL;
  384.         }
  385.         delta = -strlen(q);
  386.         for (p = a->kb_string; get_fs_byte(p); p++)
  387.             delta++;
  388.         first_free = func_table[NR_FUNC - 1] +
  389.             strlen(func_table[NR_FUNC - 1]) + 1;
  390.         if (
  391.             delta > 0 &&
  392.             first_free + delta > func_buf + FUNC_BUFSIZE
  393.         )
  394.             return -EINVAL;
  395.         if (i < NR_FUNC - 1) {
  396.             memmove(
  397.                 func_table[i + 1] + delta,
  398.                 func_table[i + 1],
  399.                 first_free - func_table[i + 1]);
  400.             for (k = i + 1; k < NR_FUNC; k++)
  401.                 if (func_table[k])  /* just to be sure */
  402.                 func_table[k] += delta;
  403.         }
  404.         for (p = a->kb_string, q = func_table[i]; ; p++, q++)
  405.             if (!(*q = get_fs_byte(p)))
  406.                 break;
  407.         return 0;
  408.     }
  409.  
  410.     case KDGKBDIACR:
  411.     {
  412.             struct kbdiacrs *a = (struct kbdiacrs *)arg;
  413.  
  414.             i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
  415.         if (i)
  416.                 return i;
  417.         put_fs_long(accent_table_size, &a->kb_cnt);
  418.         memcpy_tofs(a->kbdiacr, accent_table,
  419.                 accent_table_size*sizeof(struct kbdiacr));
  420.         return 0;
  421.     }
  422.  
  423.     case KDSKBDIACR:
  424.     {
  425.             struct kbdiacrs *a = (struct kbdiacrs *)arg;
  426.         unsigned int ct;
  427.  
  428.             i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
  429.         if (i)
  430.                 return i;
  431.         ct = get_fs_long(&a->kb_cnt);
  432.         if (ct >= MAX_DIACR)
  433.                 return -EINVAL;
  434.         accent_table_size = ct;
  435.         memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
  436.         return 0;
  437.     }
  438.  
  439.     case KDGETLED:
  440.         i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
  441.         if (i)
  442.             return i;
  443.         put_fs_byte(kbd->ledstate, (char *) arg);
  444.         return 0;
  445.  
  446.     case KDSETLED:
  447.         if (arg & ~7)
  448.             return -EINVAL;
  449.         kbd->ledstate = arg;
  450. #ifdef __pc_stuff__
  451.         set_leds();
  452. #endif
  453.         return 0;
  454.  
  455.     case VT_SETMODE:
  456.     {
  457.         struct vt_mode *vtmode = (struct vt_mode *)arg;
  458.         char mode;
  459.  
  460.         i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
  461.         if (i)
  462.             return i;
  463.         mode = get_fs_byte(&vtmode->mode);
  464.         if (mode != VT_AUTO && mode != VT_PROCESS)
  465.             return -EINVAL;
  466.         vt_cons[console].vt_mode.mode = mode;
  467.         vt_cons[console].vt_mode.waitv = get_fs_byte(&vtmode->waitv);
  468.         vt_cons[console].vt_mode.relsig = get_fs_word(&vtmode->relsig);
  469.         vt_cons[console].vt_mode.acqsig = get_fs_word(&vtmode->acqsig);
  470.         /* the frsig is ignored, so we set it to 0 */
  471.         vt_cons[console].vt_mode.frsig = 0;
  472.         vt_cons[console].vt_pid = current->pid;
  473.         vt_cons[console].vt_newvt = 0;
  474.         return 0;
  475.     }
  476.  
  477.     case VT_GETMODE:
  478.     {
  479.         struct vt_mode *vtmode = (struct vt_mode *)arg;
  480.  
  481.         i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
  482.         if (i)
  483.             return i;
  484.         put_fs_byte(vt_cons[console].vt_mode.mode, &vtmode->mode);
  485.         put_fs_byte(vt_cons[console].vt_mode.waitv, &vtmode->waitv);
  486.         put_fs_word(vt_cons[console].vt_mode.relsig, &vtmode->relsig);
  487.         put_fs_word(vt_cons[console].vt_mode.acqsig, &vtmode->acqsig);
  488.         put_fs_word(vt_cons[console].vt_mode.frsig, &vtmode->frsig);
  489.         return 0;
  490.     }
  491.  
  492.     /*
  493.      * Returns global vt state. Note that VT 0 is always open, since
  494.      * it's an alias for the current VT, and people can't use it here.
  495.      */
  496.     case VT_GETSTATE:
  497.     {
  498.         struct vt_stat *vtstat = (struct vt_stat *)arg;
  499.         unsigned short state, mask;
  500.  
  501.         i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
  502.         if (i)
  503.             return i;
  504.         put_fs_word(fg_console + 1, &vtstat->v_active);
  505.         state = 1;    /* /dev/tty0 is always open */
  506.         for (i = 1, mask = 2; i <= NR_CONSOLES; ++i, mask <<= 1)
  507.             if (tty_table[i] && tty_table[i]->count > 0)
  508.                 state |= mask;
  509.         put_fs_word(state, &vtstat->v_state);
  510.         return 0;
  511.     }
  512.  
  513.     /*
  514.      * Returns the first available (non-opened) console.
  515.      */
  516.     case VT_OPENQRY:
  517.         i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
  518.         if (i)
  519.             return i;
  520.         for (i = 1; i <= NR_CONSOLES; ++i)
  521.             if (!tty_table[i] || tty_table[i]->count == 0)
  522.                 break;
  523.         put_fs_long(i <= NR_CONSOLES ? i : -1, (unsigned long *)arg);
  524.         return 0;
  525.  
  526.     /*
  527.      * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
  528.      * with num >= 1 (switches to vt 0, our console) are not allowed, just
  529.      * to preserve sanity.
  530.      */
  531.     case VT_ACTIVATE:
  532.         if (arg == 0 || arg > NR_CONSOLES)
  533.             return -ENXIO;
  534. #ifdef __notyet__
  535.         change_console(arg - 1);
  536. #endif
  537.         return 0;
  538.  
  539.     /*
  540.      * wait until the specified VT has been activated
  541.      */
  542.     case VT_WAITACTIVE:
  543.         if (arg == 0 || arg > NR_CONSOLES)
  544.             return -ENXIO;
  545.         while (fg_console != arg - 1)
  546.         {
  547.             if (vt_waitactive() < 0)
  548.                 return -EINTR;
  549.         }
  550.         return 0;
  551.  
  552.     /*
  553.      * If a vt is under process control, the kernel will not switch to it
  554.      * immediately, but postpone the operation until the process calls this
  555.      * ioctl, allowing the switch to complete.
  556.      *
  557.      * According to the X sources this is the behavior:
  558.      *    0:    pending switch-from not OK
  559.      *    1:    pending switch-from OK
  560.      *    2:    completed switch-to OK
  561.      */
  562.     case VT_RELDISP:
  563.         if (vt_cons[console].vt_mode.mode != VT_PROCESS)
  564.             return -EINVAL;
  565.  
  566.         /*
  567.          * Switching-from response
  568.          */
  569.         if (vt_cons[console].vt_newvt >= 0)
  570.         {
  571.             if (arg == 0)
  572.                 /*
  573.                  * Switch disallowed, so forget we were trying
  574.                  * to do it.
  575.                  */
  576.                 vt_cons[console].vt_newvt = -1;
  577.  
  578.             else
  579.             {
  580.                 /*
  581.                  * The current vt has been released, so
  582.                  * complete the switch.
  583.                  */
  584.                 int newvt = vt_cons[console].vt_newvt;
  585.                 vt_cons[console].vt_newvt = -1;
  586.                 complete_change_console(newvt);
  587.             }
  588.         }
  589.  
  590.         /*
  591.          * Switched-to response
  592.          */
  593.         else
  594.         {
  595.             /*
  596.              * If it's just an ACK, ignore it
  597.              */
  598.             if (arg != VT_ACKACQ)
  599.                 return -EINVAL;
  600.         }
  601.  
  602.         return 0;
  603.  
  604. #ifdef __notyet__
  605.     case PIO_FONT:
  606.         return con_set_font((char *)arg);
  607.         /* con_set_font() defined in console.c */
  608.  
  609.     case GIO_FONT:
  610.         return con_get_font((char *)arg);
  611.         /* con_get_font() defined in console.c */
  612.  
  613.     case PIO_SCRNMAP:
  614.         return con_set_trans((char *)arg);
  615.         /* con_set_trans() defined in console.c */
  616.  
  617.     case GIO_SCRNMAP:
  618.         return con_get_trans((char *)arg);
  619.         /* con_get_trans() defined in console.c */
  620. #endif
  621.  
  622.     default:
  623.         return -EINVAL;
  624.     }
  625. }
  626.